local Scope = import("./Scope.lua");

local ScopeExpr = commonlib.inherit(commonlib.ToolBase, {});

ScopeExpr:Property("Expr");              -- 表达试
ScopeExpr:Property("CallBack");          -- 值回调
ScopeExpr:Property("Scope");             -- 表达式环境
ScopeExpr:Property("Value");             -- 值
ScopeExpr:Property("G");                 -- G

function ScopeExpr:ctor()
    self.__index_scope_key_map__ = {};    -- 依赖项
    self.__callback__ = function()
        local G = self:GetG();
        -- 移除旧依赖回调
        for scope, key_map in pairs(self.__index_scope_key_map__) do
            for key in pairs(key_map) do
                G.__remove_scope_key_callback__(scope, key, self.__callback__);
            end
        end

        local value, index_scope_key_map = G.__call_scope_expr__(self:GetExpr(), self:GetScope());
        self.__index_scope_key_map__ = index_scope_key_map;
        -- 注册新依赖回调
        for scope, key_map in pairs(index_scope_key_map) do
            for key in pairs(key_map) do
                -- print("register index depend:", self:GetExpr(), scope, key);
                G.__register_scope_key_callback__(scope, key, self.__callback__);
            end
        end

        local callback = self:GetCallBack();
        if (type(callback) == "function" and self:GetValue() ~= value) then
            self:SetValue(value); 
            callback(value);
        end
    end
end

function ScopeExpr:Init(G, expr, defaultValue, scope, callback)
    self:SetG(G);
    self:SetExpr(expr);
    self:SetValue(defaultValue);
    self:SetScope(scope);
    self:SetCallBack(callback);
    self:Refresh();
    return self;
end

function ScopeExpr:Refresh()
    self.__callback__();
end

return function(window)
    local G = window:GetParams().G;

    G = G or {};

    setmetatable(G, {__index = _G});

    G.CloseWindow = function()
        window:Close();
    end

    window:SetG(G);

    local scope = Scope(window:GetG());

    local index_scope_key_map = nil;
    local newindex_socpe_key_map = nil;
    local all_scope_key_callback_map = {};

    -- 读取回调
    scope.__index_global_callback__ = function(scope, key)
        -- print("__index_global_callback__", scope, key)
        index_scope_key_map = index_scope_key_map or {};
        index_scope_key_map[scope] = index_scope_key_map[scope] or {};
        index_scope_key_map[scope][key] = true;
    end

    -- 写入回调
    scope.__newindex_global_callback__ = function(scope, key, newval, oldval)
        -- print("__newindex_global_callback__", scope, key)
        newindex_socpe_key_map = newindex_socpe_key_map or {};
        newindex_socpe_key_map[scope] = newindex_socpe_key_map[scope] or {};
        newindex_socpe_key_map[scope][key] = true;
    end

    G.__register_scope_key_callback__ = function(scope, key, callback) 
        all_scope_key_callback_map[scope] = all_scope_key_callback_map[scope] or {};
        all_scope_key_callback_map[scope][key] = all_scope_key_callback_map[scope][key] or {};
        all_scope_key_callback_map[scope][key][callback] = callback;
    end

    G.__remove_scope_key_callback__ = function(scope, key, callback)
        all_scope_key_callback_map[scope] = all_scope_key_callback_map[scope] or {};
        all_scope_key_callback_map[scope][key] = all_scope_key_callback_map[scope][key] or {};
        all_scope_key_callback_map[scope][key][callback] = nil;
    end

    G.__trigger_scope_key_callback__ = function(scope, key) 
        all_scope_key_callback_map[scope] = all_scope_key_callback_map[scope] or {};
        all_scope_key_callback_map[scope][key] = all_scope_key_callback_map[scope][key] or {};
        for _, callback in pairs(all_scope_key_callback_map[scope][key]) do callback() end
    end

    -- 定时冲刷
    G.__flush_newindex_scope_key_map__ = function()
        if (not newindex_socpe_key_map) then return end 
        local scope_key_map = newindex_socpe_key_map;
        newindex_socpe_key_map = nil;

        for scope, key_map in pairs(scope_key_map) do
            for key in pairs(key_map) do
                G.__trigger_scope_key_callback__(scope, key);
            end
        end
    end

    -- 主动调用
    G.__call_scope_expr__ = function(expr, scope)
        -- print("=========================begin depend=======================")
        -- commonlib.cleartable(index_scope_key_map);
        index_scope_key_map = nil;
        local value = commonlib.dostring(expr, env or scope);
        -- print("=========================end depend=======================")
        return value, index_scope_key_map;
    end

    -- 新建响应式表达式
    G.__new_scope_expr__ = function(expr, defaultValue, scope, callback)
        return ScopeExpr:new():Init(G, expr, defaultValue, scope, callback);
    end

    return scope;
end